using UnityEngine;
using System.Collections;
using Game.Player;
using UnityEngine.UI;
using Game.UI;
using System;

namespace Game.Global.Helper
{
    /// <summary>
    /// 检查Player是否到达检查点，并且执行特定行为
    /// <para>用于教学关卡或其他需要player到特定地点即执行的地方</para>
    /// </summary>
    public class CheckPointBase : MonoBehaviour
    {

        /// <summary>
        /// 当条件均满足，检查点被触发时
        /// </summary>
        CallbackFunc m_onCheckPointTriggered = null;

        /// <summary>
        /// 还有其他触发的条件
        /// </summary>
        BoolCallbackFunc m_otherCheckCondition = null;

        ///// <summary>
        ///// 检查触发条件的时间间隔
        ///// </summary>
        //float m_checkOtherConditionDeltaTime = 0;

        bool m_isChecked = false;


        /// <summary>
        /// 提示文本，用于不断放大缩小以提醒Player
        /// </summary>
        [SerializeField] RectTransform m_hintUI;
        //[SerializeField] float m_scaleToMaxSize = 1.1f;
        [SerializeField] int m_hintUIJumpCount = 2;
        [SerializeField] float m_hintUIJumpSpeed = 10;
        [SerializeField] Transform m_playerTrans;

        [Tooltip("用于进入碰撞后的持续性检查，将会持续一小段时间，用于一些需要某些条件，但是无法立即满足的情况。")]
        [SerializeField] float m_continualCheckingTime = 0f;
        protected bool m_isContinualChecking = false;

        protected void Start()
        {
            Init();

            if (m_playerTrans == null)
            {
                m_playerTrans = PlayerDelegate.playerTransform;
            }

            GameControllerBase.AddOnGameReplay(() =>
                {
                    //Reset:
                    m_isChecked = false;

                    TrunHintUI(true);
                });
        }

        protected void OnTriggerEnter(Collider col)
        {
            if (col.transform == m_playerTrans )
            {
                DoCheckCondition();

                //还需要连续检查
                if (!m_isChecked && m_continualCheckingTime > 0)
                {
                    if (!m_isContinualChecking)
                    {
                        //类似上锁，一旦进入连续检查，就不会再启动同一个协程：
                        m_isContinualChecking = true;

                        StartCoroutine(GameObjFunc.IUpdateDo(m_continualCheckingTime, 0.1f, DoCheckCondition,()=> { m_isContinualChecking = false; }));//开始持续检查
                    }
                }
            }
        }

        protected virtual void Init()
        {
            //当玩家触发检查点时的监听：
            SetOnCheckpointTriggered(OnCheckPointTriggered);

            //有检查点需要设置打开的，则先通知关闭
            InitTryHideObjs(m_objsToEnableOnTrigger);

            InitUI();

        }

        //Public part:
        /// <summary>
        /// 设置检查点被玩家进入时的动作
        /// </summary>
        /// <param name="funcOnTriggered">Func on triggered.</param>
        public void SetOnCheckpointTriggered(CallbackFunc funcOnTriggered)
        {
            m_onCheckPointTriggered = funcOnTriggered;
        }

        /// <summary>
        /// 指定还需满足何种条件才触发检查点
        /// </summary>
        /// <param name="otherCheckCondition">Other check condition.</param>
        public void SetCheckCondition(BoolCallbackFunc otherCheckCondition)
        {
            m_otherCheckCondition = otherCheckCondition;
        }

        /// <summary>
        /// 是否已经触发
        /// </summary>
        public bool IsChecked
        {
            get
            {
                return m_isChecked;
            }
        }

        /// <summary>
        /// 恢复UI跳动效果
        /// </summary>
        protected void RevertUICoroutine()
        {
            if (m_hintUI != null)
            {
                //Set UI & UI Ani
                StartCoroutine(HighLightHintText());
            }
        }


        private void DoCheckCondition()
        {
            if (m_preCheckPoint.Length > 0)
            {
                for (int i = 0; i < m_preCheckPoint.Length; i++)
                {
                    if (m_preCheckPoint!=null && !m_preCheckPoint[i].IsChecked)
                    {
                        //直接返回掉，因为前提条件未满足
                        return ;
                    }
                }
                Debug.Log("前提检查点满足");
            }

            if (m_isContinualChecking && m_continualCheckDistanceToPlayer > 0)
            {
                if (Player.PlayerDelegate.playerTransform.SqrDistanceTo(this.transform.position) > Mathf.Pow(m_continualCheckDistanceToPlayer, 2))
                {
                    Debug.Log("距离过远");
                    return ;
                }
            }
            

            if (m_isChecked
                || (m_otherCheckCondition != null && m_otherCheckCondition() == false))
            {
                return;
            }

            //Is player & checked
            m_onCheckPointTriggered();
            m_isChecked = true;

            TrunHintUI(false);
        }

        IEnumerator HighLightHintText()
        {
            //Vector3 srcSize = m_hintUI.localScale;
            //Vector3 toSize = m_hintUI.localScale * m_scaleToMaxSize;

            WaitForSeconds wait = new WaitForSeconds(1);

            while (!IsChecked)
            {
                if (m_hintUI)
                {
                    yield return GameUIFuncs.IDoJumpUpUI(m_hintUI, true, m_hintUIJumpCount, m_hintUIJumpSpeed);//Jump UI是有点问题的：对于Time无法保证阶段时间一样，所以此处不在结束时返回原位置
                }

                //yield return GameUIFuncs.IScaleUITo(m_hintUI, toSize);
                //此处应该Start出N个协程？
                yield return wait;

                //GameObjFunc.RotateYToTransform(transform, Camera.main.transform);

                if (Camera.main != null)
                {
                    //目前bug：切换camera时，则不会看向镜头
                    GameObjFunc.RotateYToTransform(m_hintCanvasTrans, Camera.main.transform);
                }

                //if (m_hintCanvasTrans != null)
                //{
                //    GameObjFunc.RotateYToTransform(m_hintCanvasTrans, m_playerTrans);
                //}
            }
        }

        #region Checkpoint
        /// <summary>
        /// 当某个教学检查点出现时
        /// </summary>
        static CallbackFuncWithGameObj g_onTeachPointShowedUp;

        /// <summary>
        /// 当某个教学检查点被检查通过时
        /// </summary>
        static CallbackFuncWithGameObj g_onTeachPointTriggered;

        [Tooltip("如果设置了先决条件，则需要先决条件满足，此处才能触发")]
        [SerializeField] CheckPointBase[] m_preCheckPoint = null;

        [Tooltip("如果设置了开启的检查点，则此检查点检查通过时，会打开对应的检查点物体")]
        [SerializeField] GameObject[] m_objsToEnableOnTrigger = null;

        [SerializeField] CheckPointType m_checkPointType = CheckPointType.CheckOnly;
        
        [Tooltip("在进入检查点后的持续一小段时间的检查时，如果玩家跑太远，则判断为false.（对于0值时不做检查）")]
        [SerializeField] float m_continualCheckDistanceToPlayer = 0;

        RectTransform m_hintCanvasTrans;

        protected void InitUI()
        {
            RevertUICoroutine();

            var hintUICanvas = GetComponentInChildren<Canvas>();
            if (hintUICanvas)
            {
                m_hintCanvasTrans = hintUICanvas.GetComponent<RectTransform>();
            }

            //本地化提示信息：
            var textHint = GetComponentInChildren<Text>();
            if (textHint)
            {
                StringHelper.LocalizeText(textHint);
            }
            Debug.Log("init :" + name);
        }

        private void InitTryHideObjs(GameObject[] m_objsToEnableOnTrigger)
        {
            foreach (var obj in m_objsToEnableOnTrigger)
            {
                if (obj != null)
                {
                    var teachPoint = obj.GetComponent<CheckPointBase>();
                    if (teachPoint != null)
                    {
                        //让检查点自己去隐藏自己：
                        teachPoint.StartCoroutine(GameObjFunc.IDelayDoSth(() => { teachPoint.gameObject.SetActive(false); }));
                    }
                    else
                    {
                        //普通obj，直接隐藏之：
                        obj.SetActive(false);
                    }
                }
            }
        }


        //---------------------------------------------------------------------------
        //				Public area
        //---------------------------------------------------------------------------
        #region Public area


        /// <summary>
        /// 监听：当教学点出现时：
        /// </summary>
        /// <param name="onSomePointShowedUp"></param>
        public static void AddOnTeachPointShowedUp(CallbackFuncWithGameObj onSomePointShowedUp)
        {
            g_onTeachPointShowedUp += onSomePointShowedUp;
        }

        /// <summary>
        /// 监听：当教学检查点被通过时：
        /// </summary>
        /// <param name="onSomePointTriggered"></param>
        public static void AddOnTeachPointTriggered(CallbackFuncWithGameObj onSomePointTriggered)
        {
            g_onTeachPointTriggered = onSomePointTriggered;
        }



        #endregion

        //---------------------------------------------------------------------------
        //				Private area
        //---------------------------------------------------------------------------
        #region Private area

        private void TrunHintUI(bool isOn)
        {
            if (m_hintUI != null)
            {
                m_hintUI.gameObject.SetActive(isOn);
            }
        }

        /// <summary>
        /// 当检查点通过检查
        /// </summary>
        private void OnCheckPointTriggered()
        {
            Debug.Log("Player enter.");

            if (m_checkPointType == CheckPointType.SetWinDirectlly)
            {
                GameControllerBase.DoGameWin();
            }

            //打开那些需要打开的物体：
            GameObjFunc.TurnOnOffObj(m_objsToEnableOnTrigger, true, (obj) => {
                var teachScript = obj.GetComponent<CheckPointBase>();
                if (teachScript != null)
                {
                    //需要额外操作：恢复UI效果，而且此行为还得等下一帧，物体被恢复了才能操作⊙﹏⊙b
                    StartCoroutine(GameObjFunc.IDelayDoSth(teachScript.RevertUICoroutine));

                    if (g_onTeachPointShowedUp != null)
                    {
                        //某个物体被打开了，则开始回调：
                        g_onTeachPointShowedUp(obj);
                    }
                }
            });

            if (g_onTeachPointTriggered != null)
            {
                //这个物体被触发了：
                g_onTeachPointTriggered(this.gameObject);
            }
        }

        #endregion


        public enum CheckPointType
        {
            CheckOnly = 0,


            SetWinDirectlly = 99,
        }
        #endregion
    }
}